package com.wei.czz.framework.common.manager;

import com.alibaba.fastjson2.JSON;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.enums.common.exportTask.TaskTypeEnum;
import com.wei.czz.common.enums.common.TaskModeEnum;
import com.wei.czz.common.enums.common.exportTask.ExportStatusEnum;
import com.wei.czz.common.enums.rabbitMQ.MqEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.property.DownloadProperty;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.common.ChoiceExportVo;
import com.wei.czz.common.vo.common.exportTask.ExportTaskVo;
import com.wei.czz.framework.blog.helper.BlogCommentHelper;
import com.wei.czz.framework.common.entity.ExportTaskEntity;
import com.wei.czz.framework.common.helper.RabbitHelper;
import com.wei.czz.framework.common.service.ExportTaskService;
import com.wei.czz.framework.game.helper.GameHelper;
import com.wei.czz.framework.rabbitMQ.message.task.ExportTaskMessage;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.Validator;

import java.util.Date;
import java.util.Objects;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2024-04-03 09:48:25
 * className: ExportTaskManager
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class ExportTaskManager {

    private static final Logger log = LoggerFactory.getLogger(ExportTaskManager.class);

    private final DownloadProperty downloadProperty;

    private final ExportTaskService exportTaskService;

    private final GameHelper gameHelper;

    private final BlogCommentHelper blogCommentHelper;

    private final RabbitHelper rabbitHelper;

    private final Validator validator;

    public String addExportTask(ExportTaskVo exportTaskVo) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        /*
            参数校验
         */
        this.validParams(exportTaskVo);

        ExportTaskEntity exportTask = new ExportTaskEntity();
        exportTask.setTaskType(exportTaskVo.getTaskType())
                .setExportMode(exportTaskVo.getExportMode())
                .setFileType(exportTaskVo.getFileType())
                .setFilePath(StringUtils.EMPTY)
                .setDataType(exportTaskVo.getDataType())
                .setDataRow(CommonEnum.ZERO.getValue())
                .setFields(JSON.toJSONString(exportTaskVo.getFields()))
                .setParams(exportTaskVo.getParams())
                .setStatus(ExportStatusEnum.ACTIVITY.getValue())
                .setDeleteStatus(CommonEnum.ZERO.getValue())
                .setStartTime(date)
                .setEndTime(date)
                .setUpdateTime(date)
                .setUpdateUser(StringUtils.EMPTY)
                .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                .setCreateTime(date)
                .setCreateUser(userPo.getUsername())
                .setCreateUserId(userPo.getUserId())
                .setRemark(StringUtils.EMPTY);
        Long taskId = exportTaskService.saveExportTask(exportTask);
        log.info("添加数据导出任务完成。taskId={}", taskId);

        if (TaskModeEnum.ASYNC.getValue().equals(exportTaskVo.getExportMode())) {
            /*
                异步导出
             */
            ExportTaskMessage exportTaskMessage = new ExportTaskMessage();
            // 设置任务主键
            exportTaskMessage.setTaskId(exportTask.getTaskId());
            // 设置任务类型
            exportTaskMessage.setTaskType(exportTaskVo.getTaskType());

            // 发送一条消息到MQ
            rabbitHelper.send(MqEnum.EXPORT_TASK, exportTaskMessage);
            log.info("异步导出数据消息发送完成");
        }

        return taskId.toString();
    }

    /**
     * 验证导出任务参数
     * @param exportTaskVo 导出任务参数对象
     */
    private void validParams(ExportTaskVo exportTaskVo) {
        TaskTypeEnum taskTypeEnum = TaskTypeEnum.get(exportTaskVo.getTaskType());
        if (Objects.isNull(taskTypeEnum)) {
            log.error("导出任务类型不存在。taskType={}", exportTaskVo.getTaskType());
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "导出任务类型不存在，请确认。");
        }
        switch (taskTypeEnum) {
            case COMMENT_LIST_EXPORT:
                /*
                    导出博客评论数据
                 */
                blogCommentHelper.validExportCommentParams(exportTaskVo);
                break;
            case GAME_EXPORT:
                /*
                    导出游戏数据
                 */
                gameHelper.validExportGameParams(exportTaskVo);
                break;
            case MENU_CHOICE_EXPORT:
            case DEPT_CHOICE_EXPORT:
                /*
                    菜单自选数据导出
                    部门自选数据导出
                 */
                ChoiceExportVo choiceExportVo = JSON.parseObject(exportTaskVo.getParams(), ChoiceExportVo.class);

                Errors errors = new BeanPropertyBindingResult(choiceExportVo, ChoiceExportVo.class.getSimpleName());
                // 校验
                validator.validate(choiceExportVo, errors);
                if (errors.hasErrors()) {
                    FieldError fieldError = errors.getFieldErrors().get(0);
                    log.info("参数值错误。taskType={} field={} errorMessage={}", taskTypeEnum.getName(),
                            fieldError.getField(), fieldError.getDefaultMessage());
                    throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), fieldError.getDefaultMessage());
                }

                if (choiceExportVo.getIdList().size() > downloadProperty.getMaxSize()) {
                    log.error("导出条数超过最大限制条数。taskType={} download.size={} maxSize={}", taskTypeEnum.getName(),
                            choiceExportVo.getIdList().size(), downloadProperty.getMaxSize());
                    throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), taskTypeEnum.getName() + "条数超过最大限制条数");
                }
                break;
            default:
                log.error("导出任务类型不存在。taskType={}", taskTypeEnum.getName());
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "导出任务类型不存在，请确认。");
        }
    }
}
